// use crate::php::zend;
use std::os::raw::c_void;
use std::ptr;

// pub use zend::Bool;
// pub use zend::Double;
// pub use zend::Long;
// pub use zend::OffT;
// pub use zend::Type;
// pub use zend::Uchar;
// pub use zend::Ulong;

pub mod array;
pub mod execute_data;
pub mod refcounted;
pub mod string;
pub mod zval;

// pub use array::*;
// pub use execute_data::*;
// pub use refcounted::*;
// pub use string::*;
// pub use zval::*;

pub use array::{Array, ArrayApi};
pub use execute_data::ExecuteData;
pub use zval::{Value, Zval};

pub type VoidPtr = *const c_void;
pub type VoidPtrMut = *mut c_void;

pub trait ToSafe {
    type SafeType;

    fn into_safe(self) -> Self::SafeType
    where
        Self: Sized,
    {
        unsafe { ptr::read(&self as *const Self as *const Self::SafeType) }
    }

    fn as_safe(&self) -> &Self::SafeType {
        unsafe { &*(self as *const Self as *const Self::SafeType) }
    }

    fn as_safe_mut(&mut self) -> &mut Self::SafeType {
        unsafe { &mut *(self as *mut Self as *mut Self::SafeType) }
    }
}

use crate::php::zend::internal_php_methods::{php_printf, zend_error};
use std::ffi::CString;

/// As the name suggests, this method is acts like a PHP echo
/// ```
/// php_echo("hello world");
/// ```
pub fn php_echo(message: &str) {
    let c_message = CString::new(message).unwrap();
    unsafe {
        php_printf(c_message.as_bytes_with_nul().as_ptr() as *const i8);
    }
}

pub fn php_error(t: usize, message: &str) {
    let c_message = CString::new(message).unwrap();
    // let mut prt = Zval::default();
    // prt.set_null();
    unsafe {
        let _ = zend_error(t, c_message.as_bytes_with_nul().as_ptr() as *const i8);
    }
}
